part of quadcoptershared;

// sample class from the web
class Point {
  num x;
  num y;

  Point(this.x, this.y);

  // Named constructor
  Point.fromJson(Map json) {
    x = json['x'];
    y = json['y'];
  }
  
  Map toJson() {
    return {
       "x": x,
      "y": y,
            
    };
  }

  
  String toString() {
    return x.toString() + "," + y.toString();
  }
}

// sample class from the web
class Velocity {
  num magnitude;  // between 0 and 100
  num direction; // radians north = 0

  Velocity(this.magnitude, this.direction);

  // Named constructor
  Velocity.fromJson(Map json) {
    magnitude = json['magnitude'];
    direction = json['direction'];
  }
  
  Map toJson() {
    return {
      "magnitude": magnitude,
        "direction": direction 
      };
  }
  
  double vx() {
    return magnitude * math.cos(direction);
  }

  double vy() {
    return magnitude * math.sin(direction);
  }

  // Equals does not work
  // this tolerates roundoff
  bool isEquivalent(Velocity o)
  {
     if((magnitude - o.magnitude).abs() > SMALL_DIFF)
      return false;
     if((direction - o.direction).abs() > SMALL_DIFF)
      return false;
        
     return true;
  }
 
}

// how far we move in a millisec
 const num V_SCALE = 0.01;
 const num SURFACE_SCALE = 1000;
 const num VELOCITY_SCALE = 1000;
 final math.Random RND = new math.Random();
 final uuid.Uuid UUIDX = new uuid.Uuid();
 const num SMALL_DIFF = 0.0001;

 // Does all the work 
 // can serialize and (I hope) run in
 // server and Browser
class QuadCopter {
  String name;
  String id;
  num x;
  num y;
  Velocity _vel;
  DateTime lastClick;
  
  // current position 
  // different on each call
  Point position()
  {
    DateTime current = new DateTime.now( );
    Duration del = current.difference(lastClick);
    num msec = del.inMilliseconds;
    num newX = x + (_vel.vx() * msec * V_SCALE);
    num newY = y + (_vel.vy() * msec * V_SCALE);
    return new Point(newX,newY);
  }
  
  void setVelocity(Velocity v) {
    _vel = v;
  }
  
  // Named constructor - takes object name
  QuadCopter(String name )   
  {
    this.name = name;
    x = RND.nextDouble() * SURFACE_SCALE;
    y = RND.nextDouble() * SURFACE_SCALE;
    _vel = new Velocity(RND.nextDouble() * VELOCITY_SCALE, 
        RND.nextDouble() *  math.PI * 2);
      lastClick = new DateTime.now();
    id = UUIDX.v4();
   }
  
 
    
  Map toJson() {
    return {
      "name": name,
        "id": id,
      "x": x,
      "y": y,
      "vel": _vel.toJson(),
      "lastClick": lastClick.toString() 
            
    };
  }


  // Equals does not work
  // this tolerates roundoff
  bool isEquivalent(QuadCopter o)
  {
    if(name != o.name)
      return false;
    if(id != o.id)
      return false;
     
    if((x - o.x).abs() > SMALL_DIFF)
      return false;
    if((y - o.y).abs() > SMALL_DIFF)
      return false;
    if((_vel.isEquivalent(o._vel)) )
      return false;
      if((lastClick.millisecond - o.lastClick.millisecond).abs() > 1)
      return false;
       
     return true;
  }
  
  // Named constructor
  // 
  QuadCopter.fromJson(Map mp) {
    populateFromMap(  mp);
  }
  
  // protected method to
  // build a map
  populateFromMap(Map mp)
  {
    name = mp['name'];
    id = mp['id'];
    x = mp['x'];
    y = mp['y'];
    _vel = new Velocity.fromJson(mp['vel']);
     lastClick =  DateTime.parse(mp['lastClick']);
   }
}
